package cn.skyquant.quant4j.jforex.sdk.strategy2;


import cn.skyquant.quant4j.sdk.enums.TradeDirection;
import com.dukascopy.api.IEngine;
import com.dukascopy.api.IOrder;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.Formatter;
import java.util.List;

public class OrderProxyManager {
    private final List<OrderProxy> buyLimitList = new ArrayList<>();  //所有多单限价挂单
    private final List<OrderProxy> buyStopList = new ArrayList<>();   //所有多单突破挂单
    private final List<OrderProxy> buyList = new ArrayList<>();       //所有成交多单
    private final List<OrderProxy> sellLimitList = new ArrayList<>(); //所有空单限价挂单
    private final List<OrderProxy> sellStopList = new ArrayList<>();  //所有空单突破挂单
    private final List<OrderProxy> sellList = new ArrayList<>();      //所有成交空单
    private OrderProxy buy_first = null;                              //多单首仓
    private OrderProxy buy_last = null;                               //多单尾仓
    private OrderProxy sell_first = null;                             //空单首仓
    private OrderProxy sell_last = null;                              //空单尾仓
    private double buy_pl_usd = 0;                               //多单盈利钱（美元）
    private double buy_pl_pip = 0;                               //多单盈利点
    private double sell_c = 0;                                   //空单手续费（美元）
    private double buy_c = 0;                                    //多单手续费（美元）
    private double sell_pl_usd = 0;                              //空单盈利钱（美元）
    private double sell_pl_pip = 0;                              //空单盈利点

    private OrderProxyManager() {
    }


    //获取盈利美元
    public double getPLUSD(TradeDirection tradeDirection) {
        return tradeDirection.isLong() ? buy_pl_usd : sell_pl_usd;
    }

    //获取盈利点数
    public double getPLPip(TradeDirection tradeDirection) {
        return tradeDirection.isLong() ? buy_pl_pip : sell_pl_pip;
    }

    //获取手续费
    public double getC(TradeDirection tradeDirection) {
        return tradeDirection.isLong() ? buy_c : sell_c;
    }

    public List<OrderProxy> getOrderList(TradeDirection tradeDirection) {
        return tradeDirection.isLong() ? buyList : sellList;
    }

    public List<OrderProxy> getLimitOrderList(TradeDirection tradeDirection) {
        return tradeDirection.isLong() ? buyLimitList : sellLimitList;
    }

    public List<OrderProxy> getStopOrderList(TradeDirection tradeDirection) {
        return tradeDirection.isLong() ? buyStopList : sellStopList;
    }

    public List<OrderProxy> getReflectOrderList(TradeDirection tradeDirection) {
        return tradeDirection.isLong() ? sellLimitList : buyLimitList;
    }

    public OrderProxy getReflectLastOrder(TradeDirection tradeDirection) {
        return tradeDirection.isLong() ? sell_last : buy_last;
    }

    public OrderProxy getFirst(TradeDirection tradeDirection) {
        return tradeDirection.isLong() ? buy_first : sell_first;
    }

    public OrderProxy getLast(TradeDirection tradeDirection) {
        return tradeDirection.isLong() ? buy_last : sell_last;
    }

    public static OrderProxyManager getOrderProxyManager(AbstractConfig config, Class<? extends AbstractComment> clazz, List<IOrder> orderList) {

        final OrderProxyManager o = new OrderProxyManager();
        for (IOrder iOrder : orderList) {
            AbstractComment abstractComment = null;
            try {
                abstractComment = clazz.newInstance();
            } catch (Exception e) {
                continue;
            }
            OrderProxy orderProxy = new OrderProxy(iOrder, abstractComment);
            if (!orderProxy.isMatch(config)) {
                continue;
            }
            IOrder order = orderProxy.order;

            if (order.getOrderCommand() == IEngine.OrderCommand.BUY && order.getState() == IOrder.State.FILLED) {
                o.buyList.add(orderProxy);
                o.buy_pl_usd += order.getProfitLossInUSD();
                o.buy_pl_pip += order.getProfitLossInPips();
                o.buy_c += order.getCommissionInUSD();
//                if (o.buy_first == null || orderProxy.seriesIndex < o.buy_first.seriesIndex) {
//                    o.buy_first = orderProxy;
//                }
//                if (o.buy_last == null || orderProxy.seriesIndex > o.buy_last.seriesIndex) {
//                    o.buy_last = orderProxy;
//                }
            } else if (order.getOrderCommand() == IEngine.OrderCommand.SELL && order.getState() == IOrder.State.FILLED) {
                o.sellList.add(orderProxy);
                o.sell_pl_usd += order.getProfitLossInUSD();
                o.sell_pl_pip += order.getProfitLossInPips();
                o.sell_c += order.getCommissionInUSD();
//                if (o.sell_first == null || orderProxy.seriesIndex < o.sell_first.seriesIndex) {
//                    o.sell_first = orderProxy;
//                }
//                if (o.sell_last == null || orderProxy.seriesIndex > o.sell_last.seriesIndex) {
//                    o.sell_last = orderProxy;
//                }
            } else if (order.getOrderCommand() == IEngine.OrderCommand.SELLLIMIT && order.getState() == IOrder.State.OPENED) {
                o.sellLimitList.add(orderProxy);
            } else if (order.getOrderCommand() == IEngine.OrderCommand.BUYLIMIT && order.getState() == IOrder.State.OPENED) {
                o.buyLimitList.add(orderProxy);
            } else if (order.getOrderCommand() == IEngine.OrderCommand.BUYSTOP && order.getState() == IOrder.State.OPENED) {
                o.buyStopList.add(orderProxy);
            } else if (order.getOrderCommand() == IEngine.OrderCommand.SELLSTOP && order.getState() == IOrder.State.OPENED) {
                o.sellStopList.add(orderProxy);
            }
        }
        o.buy_first = o.buyList.stream().min(Comparator.comparingInt(x -> x.label.seriedIndex)).get();
        o.buy_last = o.buyList.stream().max(Comparator.comparingInt(x -> x.label.seriedIndex)).get();
        o.sell_first = o.sellList.stream().min(Comparator.comparingInt(x -> x.label.seriedIndex)).get();
        o.sell_last = o.sellList.stream().max(Comparator.comparingInt(x -> x.label.seriedIndex)).get();
        return o;
    }

    @Override
    public String toString() {
        Formatter formatter = new Formatter();
        formatter.format("buyList=%d,buyLimitList=%d,buyStopList=%d,sellList=%d,sellLimitList=%d,sellStopList=%d",
                buyList.size(), buyLimitList.size(), buyStopList.size(),
                sellList.size(), sellLimitList.size(), sellStopList.size());
        return formatter.toString();
    }
}
